package com.heqiang.utils;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

public class DateUtils {

    private static Logger logger = LoggerFactory.getLogger(DateUtils.class);

    public final static String formatStr_yyyyMMddHHmmss = "yyyy-MM-dd HH:mm:ss";
    public final static String formatStr_yyyyMMddHHmm = "yyyy-MM-dd HH:mm";
    public final static String formatStr_yyyyMMddHH = "yyyy-MM-dd HH";
    public final static String formatStr_yyyyMMdd = "yyyy-MM-dd";
    public final static String formatStr_yyyyMMdd2 = "yyyyMMdd";
    public final static String formatStr_yyyy = "yyyy";
    public final static String formatStr_yyyy年MM月dd日HHmm = "yyyy年MM月dd日 HH:mm";
    public final static String formatStr_MMdd_EE_HHmm = "MM/dd EEEE HH:mm";
    public final static String formatStr_MMdd_HHmm = "MM/dd HH:mm";
    public final static String formatStr_HHmm = "HH:mm";
    public final static String formatStr_MMdd = "MM/dd";
    public final static String formatStr_MM_dd = "MM-dd";
    public final static String formatStr_MMdd2 = "MM月dd日";
    public final static String formatStr_MMddHHmm = "MM-dd HH:mm";
    public final static String formatStr_yyyyMMddHHmmss1 = "yyyy/MM/dd HH:mm:ss";
    public final static String formatStr_yyyyMMddHHmmss2 = "yyyyMMddHHmmss";
    public final static String formatStr_HHMMSS = "HH:mm:ss";
    public final static String formatStr_MM = "MM";
    public final static String formatStr_yyyy年MM月dd日 = "yyyy年MM月dd日";
    public final static String formatStr_yyyyMMddTHHmmssZ = "yyyy-MM-dd'T'HH:mm:ss'Z'";

    /**
     * 获取今天0点的时间
     *
     * @return
     * @author linjia
     * @datetime 2018年11月2日 下午5:29:38
     */
    public static String getTodayTime() {
        Date now = new Date();
        String nowStr = DateUtils.dateToString(now, DateUtils.formatStr_yyyyMMdd);
        return nowStr + " 00:00:00";
    }


    //获取当前时间的前一个小时
    public static Date getInteger() {
        Calendar calendar = Calendar.getInstance();
        /* HOUR_OF_DAY 指示一天中的小时 */
        calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) - 1);
        return calendar.getTime();
    }


    /**
     * 获取当前时间前几天的日期
     *
     * @param day :
     * @return : java.lang.String
     * @author linjia
     * @date 2019/4/8 14:34
     */
    public static Date getNearDay(Integer day) {
        Calendar ca = Calendar.getInstance();
        ca.setTime(new Date());
        ca.set(Calendar.DATE, ca.get(Calendar.DATE) - day);
        return ca.getTime();
    }

    public static String getNearDay(Integer day, Date date) {
        Calendar ca = Calendar.getInstance();
        ca.setTime(date);
        ca.set(Calendar.DATE, ca.get(Calendar.DATE) - day);
        return dateToString(ca.getTime(), formatStr_yyyyMMdd);
    }

    // 获取上周的开始时间
    @SuppressWarnings("unused")
    public static Date getBeginDayOfLastWeek() {
        Date date = new Date();
        if (date == null) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int dayofweek = cal.get(Calendar.DAY_OF_WEEK);
        if (dayofweek == 1) {
            dayofweek += 7;
        }
        cal.add(Calendar.DATE, 2 - dayofweek - 7);
        return getDayStartTime(cal.getTime());
    }

    public static Date getLastWeekStart(Date date) {
        if (date == null) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int dayofweek = cal.get(Calendar.DAY_OF_WEEK);
        if (dayofweek == 1) {
            dayofweek += 7;
        }
        cal.add(Calendar.DATE, 2 - dayofweek - 7);
        return getDayStartTime(cal.getTime());
    }

    public static Date getLastSaturday(Date date) {
        if (date == null) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
        if (dayOfWeek == 7) {
            dayOfWeek = 0;
        }
        cal.add(Calendar.DATE, -dayOfWeek - 7);
        return getDayStartTime(cal.getTime());
    }

    public static Date getLastFriday(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(getLastSaturday(date));
        cal.add(Calendar.DAY_OF_WEEK, 6);
        Date weekEndSta = cal.getTime();
        return getDayEndTime(weekEndSta);
    }

    // 获取上周的结束时间
    public static Date getEndDayOfLastWeek() {
        Calendar cal = Calendar.getInstance();
        cal.setTime(getBeginDayOfLastWeek());
        cal.add(Calendar.DAY_OF_WEEK, 6);
        Date weekEndSta = cal.getTime();
        return getDayEndTime(weekEndSta);
    }

    // 获取上周的结束时间
    public static Date getLastWeekEnd(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(getLastWeekStart(date));
        cal.add(Calendar.DAY_OF_WEEK, 6);
        Date weekEndSta = cal.getTime();
        return getDayEndTime(weekEndSta);
    }

    // 获取本周的开始时间
    @SuppressWarnings("unused")
    public static Date getBeginDayOfWeek() {
        Date date = new Date();
        if (date == null) {
            return null;
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        int dayofweek = cal.get(Calendar.DAY_OF_WEEK);
        if (dayofweek == 1) {
            dayofweek += 7;
        }
        cal.add(Calendar.DATE, 2 - dayofweek);
        return getDayStartTime(cal.getTime());
    }

    // 获取本周的结束时间
    public static Date getEndDayOfWeek() {
        Calendar cal = Calendar.getInstance();
        cal.setTime(getBeginDayOfWeek());
        cal.add(Calendar.DAY_OF_WEEK, 6);
        Date weekEndSta = cal.getTime();
        return getDayEndTime(weekEndSta);
    }


    // 获取本月的开始时间
    public static Date getBeginDayOfMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(getNowYear(), getNowMonth() - 1, 1);
        return getDayStartTime(calendar.getTime());
    }

    // 获取本月的结束时间
    public static Date getEndDayOfMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(getNowYear(), getNowMonth() - 1, 1);
        int day = calendar.getActualMaximum(5);
        calendar.set(getNowYear(), getNowMonth() - 1, day);
        return getDayEndTime(calendar.getTime());
    }


    // 获取上月的开始时间
    public static Date getBeginDayOfLastMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(getNowYear(), getNowMonth() - 2, 1);
        return getDayStartTime(calendar.getTime());
    }

    // 获取上月的结束时间
    public static Date getEndDayOfLastMonth() {
        Calendar calendar = Calendar.getInstance();
        calendar.set(getNowYear(), getNowMonth() - 2, 1);
        int day = calendar.getActualMaximum(5);
        calendar.set(getNowYear(), getNowMonth() - 2, day);
        return getDayEndTime(calendar.getTime());
    }


    // 获取今年是哪一年
    public static Integer getNowYear() {
        Date date = new Date();
        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
        gc.setTime(date);
        return Integer.valueOf(gc.get(1));
    }

    // 获取本月是哪一月
    public static int getNowMonth() {
        Date date = new Date();
        GregorianCalendar gc = (GregorianCalendar) Calendar.getInstance();
        gc.setTime(date);
        return gc.get(2) + 1;
    }

    /**
     * 通过时间秒毫秒数判断两个时间的间隔
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int differentDaysByMillisecond(Date date1, Date date2) {
        logger.info("`````````" + date2.getTime() + ":" + date1.getTime() + ":" + (date2.getTime() - date1.getTime()));
        return (int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24));
    }

    /**
     * 计算两天相差天数
     *
     * @param dateStr1
     * @param dateStr2
     * @return
     */
    public static int differentDaysByMillisecond(String dateStr1, String dateStr2) {
        SimpleDateFormat format = new SimpleDateFormat(formatStr_yyyyMMddHHmmss);
        try {
            if (StringUtils.isBlank(dateStr1) || StringUtils.isBlank(dateStr2)) {
                return 0;
            }
            Date date1 = format.parse(dateStr1);
            Date date2 = format.parse(dateStr2);
            return differentDaysByMillisecond(date1, date2);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return 0;

    }


    // 获取某个日期的开始时间
    public static Timestamp getDayStartTime(Date d) {
        Calendar calendar = Calendar.getInstance();
        if (null != d)
            calendar.setTime(d);
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
                calendar.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        calendar.set(Calendar.MILLISECOND, 0);
        return new Timestamp(calendar.getTimeInMillis());
    }

    // 获取某个日期的结束时间
    public static Timestamp getDayEndTime(Date d) {
        Calendar calendar = Calendar.getInstance();
        if (null != d)
            calendar.setTime(d);
        calendar.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH),
                calendar.get(Calendar.DAY_OF_MONTH), 23, 59, 59);
        calendar.set(Calendar.MILLISECOND, 999);
        return new Timestamp(calendar.getTimeInMillis());
    }


    public static String dateToString(Date date, String toFormatStr) {
        try {
            return new SimpleDateFormat(toFormatStr).format(date);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * @param dateTime
     * @return java.lang.String
     * @Author liujiawen
     * @Description 获取n天前的日期
     * @Date 2020/4/1 14:27
     **/
    public static String getNearDate(Integer dateTime) {
        return DateUtils.dateToString(getNearDay(dateTime), DateUtils.formatStr_yyyyMMdd);
    }

    /**
     * @param hour     获取某个整点
     * @param dateTime 获取那一天
     * @return java.lang.String
     * @Author liujiawen
     * @Description 获取今日的某个整点 0:今日2000-01-01 00:00:00，1:今日2000-01-01 01:00:00
     * @Date 2020/4/3 18:52
     **/
    public static String getDayHour(Integer hour, Integer dateTime) {
        Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT+8"));
        calendar.setTime(new Date());
        calendar.add(Calendar.DATE, dateTime);
        calendar.set(Calendar.HOUR_OF_DAY, hour);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        return DateUtils.dateToString(calendar.getTime(), DateUtils.formatStr_yyyyMMddHHmmss);
    }


    /**
     * 0:今日，1昨日，2前日，3本周，4上周，5本月，6上月
     *
     * @param dateTime :
     * @return : java.util.List<java.lang.String>
     * @author linjia
     * @date 2019/8/15 17:01
     */
    public static List<String> countDate(Integer dateTime) {
        List<String> dateTimes = new ArrayList<>();
        if (dateTime == 0) {
            dateTimes.add(DateUtils.dateToString(new Date(), DateUtils.formatStr_yyyyMMdd) + " 00:00:00");
            dateTimes.add(DateUtils.dateToString(new Date(), DateUtils.formatStr_yyyyMMdd) + " 23:59:59");
            return dateTimes;
        } else if (dateTime == 1 || dateTime == 2) {
            dateTimes.add(DateUtils.dateToString(getNearDay(dateTime), DateUtils.formatStr_yyyyMMdd) + " 00:00:00");
            dateTimes.add(DateUtils.dateToString(getNearDay(dateTime), DateUtils.formatStr_yyyyMMdd) + " 23:59:59");
            return dateTimes;
        } else if (dateTime == 3) {
            dateTimes.add(DateUtils.dateToString(getBeginDayOfWeek(), DateUtils.formatStr_yyyyMMddHHmmss));
            dateTimes.add(DateUtils.dateToString(getEndDayOfWeek(), DateUtils.formatStr_yyyyMMddHHmmss));
            return dateTimes;
        } else if (dateTime == 4) {
            dateTimes.add(DateUtils.dateToString(getBeginDayOfLastWeek(), DateUtils.formatStr_yyyyMMddHHmmss));
            dateTimes.add(DateUtils.dateToString(getEndDayOfLastWeek(), DateUtils.formatStr_yyyyMMddHHmmss));
            return dateTimes;
        } else if (dateTime == 5) {
            dateTimes.add(DateUtils.dateToString(getBeginDayOfMonth(), DateUtils.formatStr_yyyyMMddHHmmss));
            dateTimes.add(DateUtils.dateToString(getEndDayOfMonth(), DateUtils.formatStr_yyyyMMddHHmmss));
            return dateTimes;
        }
        dateTimes.add(DateUtils.dateToString(getBeginDayOfLastMonth(), DateUtils.formatStr_yyyyMMddHHmmss));
        dateTimes.add(DateUtils.dateToString(getEndDayOfLastMonth(), DateUtils.formatStr_yyyyMMddHHmmss));
        return dateTimes;
    }

    public static List<String> getDate(Integer dateTime) {
        List<String> dateTimes = new ArrayList<>();
        if (dateTime == 0) {
            dateTimes.add(DateUtils.dateToString(new Date(), DateUtils.formatStr_yyyyMMdd));
            dateTimes.add(DateUtils.dateToString(new Date(), DateUtils.formatStr_yyyyMMdd));
            return dateTimes;
        } else if (dateTime == 1 || dateTime == 2) {
            dateTimes.add(DateUtils.dateToString(getNearDay(dateTime), DateUtils.formatStr_yyyyMMdd));
            dateTimes.add(DateUtils.dateToString(getNearDay(dateTime), DateUtils.formatStr_yyyyMMdd));
            return dateTimes;
        } else if (dateTime == 3) {
            dateTimes.add(DateUtils.dateToString(getBeginDayOfWeek(), DateUtils.formatStr_yyyyMMdd));
            dateTimes.add(DateUtils.dateToString(getEndDayOfWeek(), DateUtils.formatStr_yyyyMMdd));
            return dateTimes;
        } else if (dateTime == 4) {
            dateTimes.add(DateUtils.dateToString(getBeginDayOfLastWeek(), DateUtils.formatStr_yyyyMMdd));
            dateTimes.add(DateUtils.dateToString(getEndDayOfLastWeek(), DateUtils.formatStr_yyyyMMdd));
            return dateTimes;
        } else if (dateTime == 5) {
            dateTimes.add(DateUtils.dateToString(getBeginDayOfMonth(), DateUtils.formatStr_yyyyMMdd));
            dateTimes.add(DateUtils.dateToString(getEndDayOfMonth(), DateUtils.formatStr_yyyyMMdd));
            return dateTimes;
        }
        dateTimes.add(DateUtils.dateToString(getBeginDayOfLastMonth(), DateUtils.formatStr_yyyyMMdd));
        dateTimes.add(DateUtils.dateToString(getEndDayOfLastMonth(), DateUtils.formatStr_yyyyMMdd));
        return dateTimes;
    }

    public static Long getFromTime(Date date) {
        long delta = new Date().getTime() - date.getTime();
        long hours = toHours(delta);
        return hours;
    }

    public static Long getFromMin(Date date) {
        long delta = new Date().getTime() - date.getTime();
        long min = toMinutes(delta);
        return min;
    }

    private static long toSeconds(long date) {
        return date / 1000L;
    }

    private static long toMinutes(long date) {
        return toSeconds(date) / 60L;
    }

    private static long toHours(long date) {
        return toMinutes(date) / 60L;
    }

    public static String DateToString(Date date, String toFormatStr) {
        try {
            return new SimpleDateFormat(toFormatStr).format(date);
        } catch (Exception e) {
            e.printStackTrace();
            return "";
        }
    }


    public static int distanceDays(String beginTime, String endTime) {
        if (StringUtils.isBlank(beginTime) || StringUtils.isBlank(endTime)) {
            return 0;
        }
        long time = strToDate(endTime).getTime() - strToDate(beginTime).getTime();
        return (int) time / (60 * 60 * 24 * 1000);

    }

    public static String distanceStr(Long time) {
        long nh = 1000 * 60 * 60;
        long nm = 1000 * 60;
        long hour = time / nh;
        long minute = time % nh / nm;
        if (hour <= 0) {
            minute = time < 60000 && time > 0 ? 1 : minute;
            return minute + "分钟";
        }
        return hour + "小时" + minute + "分钟";
    }

    public static Date strToDate(String dateString) {
        //1、定义转换格式
        SimpleDateFormat formatter = new SimpleDateFormat(formatStr_yyyyMMdd);
        Date date = null;
        try {
            date = formatter.parse(dateString);
        } catch (ParseException e) {
            e.printStackTrace();

        }
        return date;
    }

    /**
     * date2比date1多的天数
     *
     * @param date1
     * @param date2
     * @return
     */
    public static int differentDays(Date date1, Date date2) {
        if (date1 == null || date2 == null) {
            return 0;
        }
        Calendar cal1 = Calendar.getInstance();
        cal1.setTime(date1);
        Calendar cal2 = Calendar.getInstance();
        cal2.setTime(date2);
        int day1 = cal1.get(Calendar.DAY_OF_YEAR);
        int day2 = cal2.get(Calendar.DAY_OF_YEAR);

        int year1 = cal1.get(Calendar.YEAR);
        int year2 = cal2.get(Calendar.YEAR);
        if (year1 != year2) {//同一年
            int timeDistance = 0;
            for (int i = year1; i < year2; i++) {
                if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) {//闰年
                    timeDistance += 366;
                } else { //不是闰年
                    timeDistance += 365;
                }
            }
            return timeDistance + (day2 - day1);
        }
        //不同年
        //System.out.println("判断day2 - day1 : " + (day2-day1));
        return day2 - day1;
    }


    /**
     * 判断当前时间是否处在查询时间范围内
     *
     * @param nowTime
     * @param beginTime1
     * @param endTime1
     * @return
     */
    public static boolean belongCalendar(Date nowTime, String beginTime1, String endTime1) {

        if (StringUtils.isBlank(beginTime1) || StringUtils.isBlank(endTime1)) {
            return true;
        }
        Date beginTime = stringToDate(beginTime1);
        Date endTime = stringToDate(endTime1);
        //设置当前时间
        Calendar date = Calendar.getInstance();
        date.setTime(nowTime);
        //设置开始时间
        Calendar begin = Calendar.getInstance();
        begin.setTime(beginTime);
        //设置结束时间
        Calendar end = Calendar.getInstance();
        end.setTime(endTime);
        //处于开始时间之后，和结束时间之前的判断
        if (date.after(begin) && date.before(end)) {
            return true;
        } else {
            return false;
        }
    }


    public static Date stringToDate(String dateString) {
        //1、定义转换格式
        SimpleDateFormat formatter = new SimpleDateFormat(formatStr_yyyyMMddHHmmss);
        Date date = null;
        try {
            date = formatter.parse(dateString);
        } catch (ParseException e) {
            e.printStackTrace();

        }
        return date;
    }

    /**
     * 对比时间大小
     *
     * @param date1
     * @param date2
     * @return
     */
    public static boolean compareDate(Date date1, Date date2) {
        try {
            Calendar c1 = Calendar.getInstance();
            Calendar c2 = Calendar.getInstance();
            c1.setTime(date1);
            c2.setTime(date2);
            if (c1.before(c2)) {
                return false;
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            return true;
        }
    }


    /**
     * 用SimpleDateFormat计算时间差
     *
     * @return String 返回值为：xx天xx小时xx分xx秒xx毫秒
     */
    public static String calculateTimeDifference(Date fromDate3, Date toDate3) throws ParseException {
        /*分钟差*/
        long from3 = fromDate3.getTime();
        long to3 = toDate3.getTime();
        int minutes = (int) ((to3 - from3) / (1000 * 60));
        System.out.println("两个时间之间的分钟差为：" + minutes);
        return (minutes / 60) + "小时" + minutes % 60 + "分钟";
    }

    public static String getFormatStringDate(String date, String format) {
        return dateToString(stringToDate(date, format), format);
    }


    public static Date stringToDate(String dateString, String strFormat) {
        try {
            Date date = new SimpleDateFormat(strFormat).parse(dateString);
            return date;
        } catch (ParseException e) {
            e.printStackTrace();
            return null;
        }
    }

    //判断是否是有效时间 9点-19点
    public static boolean isValid() {
        //Date endDate = startDate;
        Date date = new Date();
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        String todayStr = DateToString(calendar.getTime(), formatStr_yyyyMMdd);
        Date startDate = stringToDate(todayStr + " 08:55:55");
        Date endDate = stringToDate(todayStr + " 19:10:00");
        return date.compareTo(startDate) >= 0 && date.compareTo(endDate) <= 0;
    }

    public static Date getDayAndHour(Date date, Integer hours) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.set(Calendar.HOUR, c.get(Calendar.HOUR) - hours);
        return c.getTime();
    }


}
